<?php
/**
 * @version $Id: DNSBL.php 181 2008-03-11 21:46:28Z mikhail.miguel $
 */

require_once dirname(dirname(dirname(dirname(__FILE__)))).'/lib/trackback/spamcheck.php';
require_once dirname(dirname(dirname(dirname(__FILE__)))).'/lib/trackback/lookupbl.php';

class SpamCheck_DNSBL extends SpamCheck {
    var $_options = array(
        'sources'       => array(
            'bl.spamcop.net'
        )
    );
    var $_senderIP;
    var $_dnsbl;

    function SpamCheck_DNSBL($options=null)
    {
        if (is_array($options)) {
            foreach ($options as $key => $val) {
                $this->_options[$key] = $val;
            }
        }
        $this->_dnsbl = new LookupBlacklist();
    }

    function check($trackback)
    {
        $result = $this->_checkSource($this->_options['sources'], $trackback);
        if(TrackbackService::isError($result)) {
            $this->_results = true;
            return $result;
        }
        return false;
    }

    function _checkSource(&$sources, $trackback)
    {
        $this->_senderIP = $this->_getIP();
        if($this->_senderIP == 'unknown' || !($this->_dnsbl->checkIP($this->_senderIP))) {
            return TrackbackService::setError('Your IP address is unknown.');
        }

        if($this->_dnsbl->setBlacklists($sources)) {
            if($this->_dnsbl->isListed($this->_dnsbl->reverseIP($this->_senderIP))) {
                return TrackbackService::setError('Your IP address, '.htmlspecialchars($this->_senderIP, ENT_QUOTES).', are listed on a blacklist db.');
            }
        }
        return false;
    }

    function _getIP()
    {
        $ip = 'unknown';
        $ip_array = array();
        if(isset($_SERVER['HTTP_X_FORWARDED_FOR']) && strpos($_SERVER['HTTP_X_FORWARDED_FOR'],',')) {
            $ip_array +=  explode(',',$_SERVER['HTTP_X_FORWARDED_FOR']);
        } elseif(isset($_SERVER['HTTP_X_FORWARDED_FOR']) && $_SERVER['HTTP_X_FORWARDED_FOR'] != '') {
            $ip_array[] = $_SERVER['HTTP_X_FORWARDED_FOR'];
        }
        if(isset($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR'] != '') {
            $ip_array[] = $_SERVER['REMOTE_ADDR'];
        }
        
        foreach ( $ip_array as $ip_s ) {
            if( !empty($ip_s) && !$this->_isPrivateNet($ip_s)){
                $ip = $ip_s;
                break;
            }
        }
        return $ip;
    }

    function _isPrivateNet($ip)
    {
        $private_ips = array(
           '127.0.0.0/8',
           '10.0.0.0/8',
           '172.16.0.0/12',
           '192.168.0.0/16'
        );

        foreach ($private_ips as $private) {
            list($net, $mask) = split('/', $private);
            if($this->_isIpInNet($ip, $net, $mask)){
                return true;
            }
        }
        return false;
    }

    function _isIpInNet($ip, $net, $mask)
    {
        $long_net = ip2long($net);
        $long_ip =  ip2long($ip);
        $binary_net = str_pad( decbin($long_net), 32, '0', 'STR_PAD_LEFT');
        $firstpart = substr($binary_net, 0, $mask);
        $binary_ip = str_pad( decbin($long_ip), 32, '0', 'STR_PAD_LEFT');
        $firstip = substr($binary_ip, 0, $mask);
        return (strcmp($firstpart, $firstip) == 0);
    }

}

?>